import './DevExtremePage.scss'
import { Graph, Shape } from '@antv/x6'
import { useRef, useState } from 'react'
import { useRequest } from 'alova/client'
import { App, Button, Skeleton } from "antd"
import { register } from '@antv/x6-react-shape'
import { useEventEmitter, useMount, useReactive } from 'ahooks'

import { Http } from '../../Utils/Api'

import { treeValue } from '../../Utils'

import { drawerStore } from '../../Config/zustand'
import { AdminRouter } from '../../Config/default'
import { GetIndexedDB } from '../../Utils/IndexedDB'
import { Encrypt, Decrypt } from '../../Utils/IndexedDB'
import { FlowMenuMapping } from '../../Config/FlowConfig'
import DevExtremeConfig from '../../Utils/DevExtremeConfig'


const { port } = window.location

const connecting = {
    router: 'manhattan',
    connector: { name: 'rounded', args: { radius: 8 } },
    anchor: 'center',
    connectionPoint: 'anchor',
    allowBlank: false,
    snap: { radius: 20 },
}

const attr = { attrs: { line: { stroke: '#A2B1C3', strokeWidth: 2, targetMarker: { name: 'block', width: 12, height: 8 } } }, zIndex: 0 }

const saveJsonInfoByUuid = async (uuid, content) => {
    try { return await Http({ method: 'post', url: 'dictionary/SaveJsonInfoByUuid', params: { uuid, content } }) }
    catch (error) { throw new Error(`保存 ${uuid} 时出错: ${error.message}`) }
}

const getJsonInfoByUuid = async (uuid) => {
    try { return await Http({ method: 'get', url: 'dictionary/GetJsonInfoByUuid', params: { uuid } }) }
    catch (error) { throw new Error(`获取 ${uuid} 配置信息时出错: ${error.message}`) }
}

const DevExtremePage = ({ url, uuid }) => {
    const { notification } = App.useApp()
    if (!url) {
        notification.error({ key: 'devPage', message: '权限不足!', description: '您为获取到当前页面权限,如有需要请及时联系管理员!', showProgress: true })
        return false
    }
    // 初始化参数
    const X6Box = useRef()
    const { updateDrawer } = drawerStore()
    const [MenuType, setMenuType] = useState()

    const { send } = useRequest(data => Http(data), { immediate: false })
    const uuids = [`MenuConfig/${url}_API`, `MenuConfig/${url}_TEM`, `MenuConfig/${url}_OPT`]

    const Init = useReactive({ API: {}, TEM: {}, OPT: {} })

    // 页面加载状态
    const [Update, setUpdate] = useState(false)
    const [PageLoading, setPageLoading] = useState(false)

    const inInitFiles = async () => {
        try {
            const content = JSON.stringify(await Encrypt({}))
            await Promise.all(uuids.map(uuid => saveJsonInfoByUuid(uuid, content)))
            notification.success({ key: 'devPage', message: '配置文件已生成!', description: '请及时完善配置文件信息!', showProgress: true })
            onGetConfigFiles()
        }
        catch (err) { console.log('文件生成失败', err) }
    }

    const onGetConfigFiles = async () => {
        setPageLoading(false)
        try {
            const [API, TEM, OPT] = await Promise.all(uuids.map(uuid => getJsonInfoByUuid(uuid)))
            Init.API = await Decrypt(API)
            Init.TEM = await Decrypt(TEM)
            Init.OPT = await Decrypt(OPT)
            setPageLoading(true)
        } catch (err) {
            const { userUuid } = await GetIndexedDB('user')
            notification.info({
                key: 'devPage',
                message: '未获取到配置!',
                description: '请检测网络或联系管理员!',
                showProgress: true,
                actions: (port || userUuid === '1e99e116-6ec0-425c-87b4-64dd2ce458e2') && (<Button type='primary' onClick={inInitFiles}>{url} 生成新配置文件</Button>)
            })
        }
    }

    useMount(async () => {
        onGetConfigFiles()
        const [{ children: menu }] = await GetIndexedDB('menu')
        const { type, uuid: twoUuid } = treeValue(menu, url, 'targetUrl')
        setMenuType(type === 'two' ? twoUuid : uuid)
    })

    const getData = () => {
        send({ method: 'get', url: 'getProject', params: { uuid: 'Process/79637b06-554b-4385-9e8f-2aec5cf22160@后台路由' } })
            .then(async res => renderFlow(await Decrypt(res)))
    }

    const renderFlow = (data) => {
        if (X6Box.current) {
            const graph = new Graph({
                interacting: false,
                container: X6Box.current,
                grid: true,
                background: { color: '#ffffff' },
                connecting: { ...connecting, createEdge() { return new Shape.Edge(attr) }, validateConnection({ targetMagnet }) { return !!targetMagnet } },
            })
            graph.fromJSON(data)
            graph.centerContent()
        } else setTimeout(() => renderFlow(data), 500);
    }

    const CustomComponent = ({ node }) => {
        const { text, waring, params } = node.attrs.text
        return (
            <div
                className={`custom-react-node${waring ? ' waring' : ''}`}
                style={params ? { cursor: 'pointer' } : {}}
                onClick={() => { if (params) onUpdateDrawer(text, params) }}
            >
                {text}
            </div>
        )
    }

    register({ shape: 'custom-react-node', component: CustomComponent })

    const onSaveFlowData = async () => {
        const optionsData = { menu: MenuType, button: [...Init.OPT.topOptions || [], ...Init.OPT.rowOptions || []] }
        send({ method: 'post', url: 'menu/AddMenuButton', params: optionsData }).then(async res => {
            const suffixMap = { 'API': Init.API, 'TEM': Init.TEM, 'OPT': Init.OPT }
            try {
                await Promise.all(uuids.map(async uuid => {
                    for (const suffix in suffixMap) {
                        if (uuid.endsWith(suffix)) return saveJsonInfoByUuid(uuid, JSON.stringify(await Encrypt(suffixMap[suffix])));
                    }
                }))
                onGetConfigFiles()
            }
            catch (err) { console.log('保存失败', err) }
            setUpdate(false)
        }).catch((err) => {
            console.log('权限保存失败', err)
        })
    }

    const onUpdateDrawer = (text, params) => {
        const defData = AdminRouter[params]
        const devTemplate = {
            FlowDataGridConfig: 'devConfig',
            FlowTreeGridConfig: 'devConfig',
            FlowOLAPGridConfig: 'devConfig',

            FlowMenuTopStyle: 'topStyle',
            FlowMenuTreStyle: 'treStyle',
            FlowMenuRowStyle: 'rowStyle',
            FlowMenuPopStyle: 'popStyle',
        }

        const devOptions = {
            FlowMenuTopClick: 'topOptions',
            FlowMenuRowClick: 'rowOptions',
            FlowMenuTreClick: 'treOptions',

        }

        const webData = devTemplate[params] ?
            Init[FlowMenuMapping[params].uuid][devTemplate[params]] :
            devOptions[params] ? Init.OPT[devOptions[params]] :
                Init[FlowMenuMapping[params].uuid]

        const data = {
            flowUrl: params,
            init: devOptions[params] ? webData : { ...defData, ...webData },
            DevEvent,
            field: devOptions[params] ? JSON.parse(JSON.stringify(Init.API.fieldArr)) : ''
        }
        updateDrawer({ title: text, type: 'SetAdminRouter', width: 560, data })
    }

    const onModifyJsonData = ({ url, data }) => {
        if (url === 'FlowMenuAPIInterface') Init.API = { ...Init.API, ...data }
        if (url === 'FlowMenuTempConfig') Init.TEM = { ...Init.TEM, ...data }
        if (url === 'FlowDataGridConfig') Init.TEM.devConfig = data
        if (url === 'FlowTreeGridConfig') Init.TEM.devConfig = data
        if (url === 'FlowOLAPGridConfig') Init.TEM.devConfig = data

        if (url === 'FlowMenuTopStyle') Init.TEM.topStyle = data
        if (url === 'FlowMenuTreStyle') Init.TEM.treStyle = data
        if (url === 'FlowMenuRowStyle') Init.TEM.rowStyle = data
        if (url === 'FlowMenuPopStyle') Init.TEM.popStyle = data
        if (url === 'FlowMenuTopClick') Init.OPT.topOptions = data
        if (url === 'FlowMenuRowClick') Init.OPT.rowOptions = data
        if (url === 'FlowMenuTreClick') Init.OPT.treOptions = data
        notification.success({ key: 'devPage', message: '信息已更新!', showProgress: true })
        DevEvent.emit({ type: 'closeForm' })
    }



    const CallBackFunc = (e) => {
        // console.log('CallBackFunc', e)
        const { type, data } = e
        const MapReturn = new Map([
            ['onRefresh', () => onGetConfigFiles()],
            ['onModifyJsonData', () => onModifyJsonData(data)],
            ['onUpDate', () => { getData(); setUpdate(true) }],
            ['onSaveFieldData', () => Init.API.fieldArr = data],
            ['top', () => onModifyJsonData({ type: '', url: 'FlowMenuTopClick', data })],
            ['row', () => onModifyJsonData({ type: '', url: 'FlowMenuRowClick', data })]
        ])
        const func = MapReturn.get(type)
        return func && func()
    }
    const DevEvent = useEventEmitter()
    DevEvent.useSubscription(CallBackFunc)

    return (
        <div className='DevExtremePage'>
            {PageLoading ?
                Update ?
                    <div className='DevExtremeFlow' >
                        <div ref={X6Box} />
                        <Button type='primary' onClick={onSaveFlowData}>保存配置文件</Button>
                    </div> :
                    <DevExtremeConfig
                        uuid={uuid}
                        url={url}
                        MenuType={MenuType}
                        APIdata={Init.API}
                        TEMdata={Init.TEM}
                        OPTdata={Init.OPT}
                        DevEvent={DevEvent}
                    /> :
                <Skeleton active paragraph={{ rows: 24 }} />
            }
        </div>
    );
};

export default DevExtremePage;